using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace Pokemon
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class LayerManager : GameComponent
    {
        private List<GameComponent>[] _layer = new List<GameComponent>[10];

        private List<GameComponent> _removeAbleGameComponent = new List<GameComponent>();

        private int _threshold;

        public LayerManager(Game game)
            : base(game)
        {
            Initialize();
        }

        public List<GameComponent> GetLayer(int index)
        {
            NormalizePriority(ref index);
            return _layer[index];
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            for (int i = 0; i < 10; i++)
            {
                _layer[i] = new List<GameComponent>();        
            }

            base.Initialize();
        }

        public void Add(GameComponent gameComponent, int priority)
        {
            NormalizePriority(ref priority);
            
            _layer[priority].Add(gameComponent);
        }

        public void Remove(GameComponent gameComponent)
        {
            _removeAbleGameComponent.Add(gameComponent);        
        }

        public int FindGameComponent(GameComponent gameComponent)
        {
            for (int i = 0; i < 10; i++)
            {
                if (_layer[i].Count > 0)
                    foreach (var component in _layer[i])
                    {
                        if (component == gameComponent)
                            return i;
                    }
            }
            return -1;
        }

        public void SetPriority(GameComponent gameComponent, int priority)
        {
            var index = FindGameComponent(gameComponent);
            if (index < 0)
                return;

            _layer[index].Remove(gameComponent);

            NormalizePriority(ref priority);
            
            _layer[priority].Add(gameComponent);
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            foreach (var gameComponent in _removeAbleGameComponent)
            {
                int index = FindGameComponent(gameComponent);
                if (index > 0)                    
                    _layer[index].Remove(gameComponent);        
            }
            
            _removeAbleGameComponent.Clear();

            for (int i = 9; i >= 0; i--)
            {
                if (_layer[i].Count > 0)
                    foreach (var gameComponent in _layer[i])
                    {
                        gameComponent.Update(gameTime);
                    }
            }            
        }

        public void Draw(GameTime gameTime)
        {
            for (int i = 0; i < 10; i++)
            {
                if (_layer[i].Count > 0)
                    foreach (var gameComponent in _layer[i])
                    {
                        if (gameComponent is DrawableGameComponent)
                            ((DrawableGameComponent)gameComponent).Draw(gameTime);
                    }
            }
        }

        public bool CheckComponentClick(Point p)
        {
            bool checkTap = false;
            for (int i = 9; i >= _threshold; i--)   //Chi kiem tra su kien tapped cho den nguong threshold
            {
                if (_layer[i].Count > 0)
                    foreach (var gameComponent in _layer[i])
                    {
                        if (gameComponent is InputManager || gameComponent is BulletManager)
                        {
                            continue;
                        }
                        checkTap = checkTap || ((ITappedInner) gameComponent).CheckTapped(p);
                    }
            }
            return checkTap;
        }
        
        public List<PanelButton> GetPanelButton()
        {
            List<PanelButton> list = new List<PanelButton>();
            for (int i = 0; i < 10; i++)
            {
                if (_layer[i].Count > 0)
                    foreach (var gameComponent in _layer[i])
                    {
                        if (gameComponent is PanelButton)
                            list.Add(gameComponent as PanelButton);
                        if (gameComponent is Chest)
                            list.Add((gameComponent as Chest).ItemPanel);
                    }
            }
            return list;
        }

        public void NormalizePriority(ref int priority)
        {
            if (priority > 9)
                priority = 9;
            if (priority < 0)
                priority = 0;                
        }

        public void SetPriorityThreshold(int threshold)
        {
            NormalizePriority(ref threshold);
            _threshold = threshold;
        }

        /// <summary>
        /// Xu ly tinh huong player chon 1 unit hoac item nhung lai dat vao 1 vi tri bat hop le
        /// </summary>
        public void FailClick()
        {
            for (int i = 0; i < 10; i++)
            {
                if (_layer[i].Count > 0)
                {
                    foreach (var gameComponent in _layer[i])
                    {
                        if (gameComponent is PanelButton)
                            (gameComponent as PanelButton).GridPushed();
                        if (gameComponent is Chest)
                            (gameComponent as Chest).ItemPanel.GridPushed();
                    }
                }
            }            
        }
    }
}
